home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 001 / pibt40s3.arc / PIBEDITR.MOD next >
Text File  |  1987-07-13  |  58KB  |  1,940 lines

  1. (*----------------------------------------------------------------------*)
  2. (*           PibEditor --- Simple screen editor for PibTerm             *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE PibEditor;
  6.  
  7. VAR
  8.    EditFileName : AnyStr;
  9.  
  10. (*----------------------------------------------------------------------*)
  11. (*           Editor --- Main program for screen editor for PibTerm      *)
  12. (*----------------------------------------------------------------------*)
  13.  
  14. PROCEDURE Editor( EditFileName : AnyStr );
  15.  
  16. CONST
  17.    MaxLines = 7000                 (* Maximum lines allowed here        *);
  18.    MaxECol  = 80                   (* Maximum length line to edit       *);
  19.  
  20. TYPE                               (* Only lines up to 80 chars can be edited *)
  21.    TextLine = STRING[MaxECol];
  22.                                    (* Points to text lines being edited *)
  23.    LinePtr = ^TextLine;
  24.                                    (* Pointers to text lines *)
  25.  
  26.    LineBufferType    = ARRAY[1..MaxLines] OF LinePtr;
  27.    LineBufferTypePtr = ^LineBufferType;
  28.  
  29. VAR
  30.    KeyNum        : INTEGER         (* Key entered as editor command input *);
  31.    CurrentLine   : INTEGER         (* Current Line being edited in file   *);
  32.    Column        : INTEGER         (* Current column in Line being edited *);
  33.    I             : INTEGER         (* General purpose index               *);
  34.    HighestLine   : INTEGER         (* Last Line in file being edited      *);
  35.    ScreenLine    : INTEGER         (* Current Line on screen              *);
  36.    ScreenCol     : INTEGER         (* Current column on screen            *);
  37.    Page_Size     : INTEGER         (* Maximum # of lines per screen       *);
  38.    InKey         : CHAR            (* Keyboard entry                      *);
  39.    SecInKey      : CHAR            (* Second character of escape sequence *);
  40.    Choice        : CHAR            (* Selected option character           *);
  41.    Ch            : CHAR            (* General purpose character           *);
  42.    IntMaxLines   : INTEGER         (* Integer maximum lines available     *);
  43.    FirstColumn   : INTEGER         (* First column displayed              *);
  44.    LastColumn    : INTEGER         (* Last column displayed               *);
  45.  
  46.                                    (* Array of pointers to text lines     *)
  47.  
  48.    LineBuffer    : LineBufferTypePtr;
  49.  
  50.                                    (* Pointer to empty Line               *)
  51.    EmptyLine     : LinePtr;
  52.                                    (* Marks tab stop columns              *)
  53.  
  54.    TabSet        : ARRAY[1..MaxECol] OF BOOLEAN;
  55.  
  56.                                    (* File to be read/written, if any     *)
  57.    TextFile      : Text_File;
  58.  
  59.    SearchString  : AnyStr          (* String to search for *);
  60.    Replacement   : AnyStr          (* String to replace selected string *);
  61.  
  62.    SecNum        : BOOLEAN         (* TRUE if escape sequence entered  *);
  63.    InsertMode    : BOOLEAN         (* TRUE if Insert mode active       *);
  64.    Edit_Done     : BOOLEAN         (* TRUE if editing session complete *);
  65.  
  66.    Local_Save    : Saved_Screen_Ptr (* Saves screen image              *);
  67.    Main_Save     : Saved_Screen_Ptr (* Saves screen image              *);
  68.  
  69. (*----------------------------------------------------------------------*)
  70. (*      Quick_Display --- display Line by writing to screen memory      *)
  71. (*----------------------------------------------------------------------*)
  72.  
  73. PROCEDURE Quick_Display( X , Y: INTEGER; S: AnyStr );
  74.  
  75. VAR
  76.    L: INTEGER;
  77.  
  78. BEGIN (* Quick_Display *)
  79.  
  80.    IF ( ORD(S[0]) > MaxECol ) THEN
  81.       S[0] := CHR(MaxECol);
  82.  
  83.    WriteSXY( S, X, Y + 1, Global_Text_Attribute );
  84.  
  85.    L := X + ORD(S[0]);
  86.  
  87.    IF ( L <= Max_Screen_Col ) THEN
  88.       BEGIN
  89.          GoToXY( L , Y );
  90.          ClrEol;
  91.       END;
  92.  
  93. END  (* Quick_Display *);
  94.  
  95. (*----------------------------------------------------------------------*)
  96. (*             DrawScreen --- Display text lines on screen              *)
  97. (*----------------------------------------------------------------------*)
  98.  
  99. PROCEDURE DrawScreen;
  100.  
  101. VAR
  102.    I:  INTEGER;
  103.    L:  INTEGER;
  104.  
  105. BEGIN (* DrawScreen *)
  106.  
  107.    FOR I := 1 TO Page_Size DO
  108.       BEGIN
  109.          L := CurrentLine - ScreenLine + I;
  110.          IF ( ( L <= HighestLine ) AND ( L > 0 ) ) THEN
  111.             Quick_Display( 1, I, LineBuffer^[ L ]^ )
  112.          ELSE
  113.             BEGIN
  114.                GoToXY( 1 , I );
  115.                ClrEol;
  116.             END;
  117.       END;
  118.  
  119. END   (* DrawScreen *);
  120.  
  121. (*----------------------------------------------------------------------*)
  122. (*   Edit_Press_Any --- display message and wait for key to be pressed  *)
  123. (*----------------------------------------------------------------------*)
  124.  
  125. PROCEDURE Edit_Press_Any( S: AnyStr );
  126.  
  127. BEGIN (* Edit_Press_Any *)
  128.  
  129.    WRITE( S );
  130.  
  131.    Read_Kbd( Ch );
  132.  
  133.    IF ( ( ORD( Ch ) = ESC ) AND KeyPressed ) THEN
  134.       READ( Kbd, Ch );
  135.  
  136. END   (* Edit_Press_Any *);
  137.  
  138. (*----------------------------------------------------------------------*)
  139. (*             NewBuffer --- Allocate memory for new text line          *)
  140. (*----------------------------------------------------------------------*)
  141.  
  142. PROCEDURE NewBuffer( VAR Buf: LinePtr );
  143.  
  144. BEGIN  (* NewBuffer *)
  145.  
  146.    NEW( Buf );
  147.  
  148. END   (* NewBuffer *);
  149.  
  150. (*----------------------------------------------------------------------*)
  151. (*             ZapBuffer --- Deallocate memory for text line            *)
  152. (*----------------------------------------------------------------------*)
  153.  
  154. PROCEDURE ZapBuffer( VAR Buf: LinePtr );
  155.  
  156. BEGIN  (* ZapBuffer *)
  157.  
  158.    IF( Buf <> EmptyLine ) THEN
  159.       BEGIN
  160.          DISPOSE( Buf );
  161.          Buf := EmptyLine;
  162.       END;
  163.  
  164. END   (* ZapBuffer *);
  165.  
  166. (*----------------------------------------------------------------------*)
  167. (*             ReadFile --- Read existing text file into memory         *)
  168. (*----------------------------------------------------------------------*)
  169.  
  170. FUNCTION ReadFile( Name: AnyStr ) : BOOLEAN;
  171.  
  172. VAR
  173.    Trunc_Lines : INTEGER;
  174.    S           : AnyStr;
  175.    L           : INTEGER;
  176.  
  177. BEGIN (* ReadFile *)
  178.                                    (* Bring up read window    *)
  179.  
  180.    Save_Partial_Screen( Local_Save, 5, 10, 75, 16 );
  181.  
  182.    Draw_Menu_Frame( 5, 10, 75, 16, Menu_Frame_Color, Menu_Title_Color,
  183.                     Menu_Text_Color, 'Read file ' + Name );
  184.  
  185.                                    (* See if text file exists *)
  186.       (*$I-*)
  187.    ASSIGN( TextFile, Name );
  188.    RESET ( TextFile );
  189.       (*$I+*)
  190.  
  191.    IF ( Int24Result <> 0 ) THEN
  192.       BEGIN
  193.          WRITELN( CHR( BELL ) );
  194.          WRITELN(' File not found');
  195.          ReadFile := TRUE;
  196.          Edit_Press_Any( ' Press any key to continue ... ');
  197.          Restore_Screen( Local_Save );
  198.          Reset_Global_Colors;
  199.          EXIT;
  200.       END;
  201.  
  202.    GoToXY( 1 , 1 );
  203.    WRITE(' Reading Line ');
  204.    ClrEol;
  205.                                    (* Keep track of truncated lines *)
  206.    Trunc_Lines := 0;
  207.  
  208.    REPEAT
  209.                                    (* Read line from input file *)
  210.       READLN( TextFile, S );
  211.                                    (* Increment line count *)
  212.  
  213.       CurrentLine := SUCC( CurrentLine );
  214.  
  215.       IF ( ( CurrentLine MOD 25 ) = 0 ) THEN
  216.          BEGIN
  217.             GoToXY( 15 , WhereY );
  218.             WRITE( CurrentLine );
  219.          END;
  220.                                    (* Allocate line if necessary *)
  221.  
  222.       IF ( LineBuffer^[CurrentLine] = EmptyLine ) THEN
  223.          NewBuffer( LineBuffer^[CurrentLine] );
  224.  
  225.                                    (* Truncate line to MaxECol characters *)
  226.       L := ORD( S[0] );
  227.  
  228.       IF ( L > MaxECol ) THEN
  229.          BEGIN
  230.             Trunc_Lines := SUCC( Trunc_Lines );
  231.             L           := MaxECol;
  232.          END;
  233.                                    (* Move input text to line buffer *)
  234.  
  235.       MOVE( S[1] , LineBuffer^[CurrentLine]^[1] , L );
  236.       LineBuffer^[CurrentLine]^[0] := CHR( L );
  237.  
  238.  
  239.       IF ( CurrentLine > IntMaxLines ) THEN
  240.          BEGIN
  241.             WRITELN;
  242.             WRITELN(' File is too long to edit with PibTerm editor.');
  243.             WRITELN(' Only ',IntMaxLines,' lines allowed.');
  244.             Edit_Press_Any( ' Press any key to continue ... ');
  245.             ReadFile := FALSE;
  246.             Restore_Screen( Local_Save );
  247.             Reset_Global_Colors;
  248.             EXIT;
  249.          END;
  250.  
  251.    UNTIL ( EOF( TextFile ) );
  252.  
  253.       (*$I-*)
  254.    CLOSE( TextFile );
  255.       (*$I+*)
  256.  
  257.    IF ( Trunc_Lines > 0 ) THEN
  258.       BEGIN
  259.          WRITELN;
  260.          WRITELN(' ', Trunc_Lines, ' lines longer than ',MaxECol:1,' characters ',
  261.                  'truncated to ',MaxECol:1,' characters.');
  262.          Edit_Press_Any( ' Press any key to continue ... ');
  263.       END;
  264.  
  265.    ReadFile := TRUE;
  266.  
  267.    Restore_Screen( Local_Save );
  268.    Reset_Global_Colors;
  269.  
  270. END   (* ReadFile *);
  271.  
  272. (*----------------------------------------------------------------------*)
  273. (*                  LoadFile --- Prepare to edit file                   *)
  274. (*----------------------------------------------------------------------*)
  275.  
  276. FUNCTION LoadFile( Name: AnyStr ) : BOOLEAN;
  277.  
  278. BEGIN (* LoadFile *)
  279.                                    (* No lines in file yet.  *)
  280.    CurrentLine := 0;
  281.  
  282.    Window( 1, 2, Max_Screen_Col, SUCC( Page_Size ) );
  283.    Clear_Window;
  284.  
  285.    IF ( Name <> '' ) THEN
  286.       LoadFile := ReadFile( Name )
  287.    ELSE
  288.       LoadFile := TRUE;
  289.  
  290.    HighestLine := CurrentLine;
  291.    CurrentLine := 1;
  292.    Column      := 1;
  293.    ScreenLine  := 1;
  294.  
  295.    DrawScreen;
  296.  
  297. END   (* LoadFile *);
  298.  
  299. (*----------------------------------------------------------------------*)
  300. (*             DispKey --- Display a function key definition            *)
  301. (*----------------------------------------------------------------------*)
  302.  
  303. PROCEDURE DispKey( S: AnyStr );
  304.  
  305. BEGIN (* DispKey *)
  306.  
  307.    TextColor( Menu_Text_Color );
  308.  
  309.    WRITE( S[1] );
  310.  
  311.    TextColor( LightGray );
  312.  
  313.    WRITE( COPY( S, 2, 80 ) );
  314.  
  315. END  (* DispKey *);
  316.  
  317. (*----------------------------------------------------------------------*)
  318. (*          DisplayKeys --- Display function key definitions            *)
  319. (*----------------------------------------------------------------------*)
  320.  
  321. PROCEDURE DisplayKeys;
  322.  
  323. BEGIN (* DisplayKeys *)
  324.  
  325.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  326.    GoToXY( 1 , Max_Screen_Line );
  327.    ClrEol;
  328.  
  329.    DispKey('1Help  ');
  330.    DispKey('2Locate  ');
  331.    DispKey('3Search  ');
  332.    DispKey('4Replace  ');
  333.    DispKey('5SaveQuit  ');
  334.    DispKey('6InsLine  ');
  335.    DispKey('7DelLine  ');
  336.    DispKey('0QuitNosave  ');
  337.  
  338.    TextColor( ForeGround_Color );
  339.  
  340.    Window( 1, 2, Max_Screen_Col, SUCC( Page_Size ) );
  341.  
  342. END   (* DisplayKeys *);
  343.  
  344. (*----------------------------------------------------------------------*)
  345. (*                  Initialize --- Initialize editor                    *)
  346. (*----------------------------------------------------------------------*)
  347.  
  348. FUNCTION Initialize( Name : AnyStr ) : BOOLEAN;
  349.  
  350. VAR
  351.    Drive: CHAR;
  352.    Path : AnyStr;
  353.    FileN: AnyStr;
  354.    FileT: AnyStr;
  355.    BadF : BOOLEAN;
  356.  
  357. BEGIN (* Initialize *)
  358.                                    (* Get # lines to display per screen *)
  359.  
  360.    Set_Screen_Size( Max_Screen_Line , Max_Screen_Col );
  361.  
  362.    Page_Size := Max_Screen_Line - 3;
  363.  
  364.                                    (* Clear screen             *)
  365.  
  366.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  367.    Clear_Window;
  368.                                    (* Start out in selected insert mode *)
  369.  
  370.    InsertMode   := Edit_Insert_Mode;
  371.  
  372.                                    (* Initialize status Line *)
  373.    TextColor( Menu_Frame_Color );
  374.  
  375.    GoToXY( 1 , 1 );
  376.    WRITE( Dupl( CHR( 205 ) , Max_Screen_Col ) );
  377.  
  378.    TextColor( Menu_Text_Color  );
  379.    GoToXY( 1 , 1 );
  380.  
  381.    IF InsertMode THEN
  382.       WRITE( 'Insert ' )
  383.    ELSE
  384.       WRITE( 'Replace' );
  385.  
  386.    TextColor( Menu_Frame_Color );
  387.    WRITE( CHR( 205 ) );
  388.  
  389.    GoToXY(1,24);
  390.    WRITE( Dupl( CHR( 196 ) , Max_Screen_Col ) );
  391.  
  392.    TextColor( Menu_Text_Color );
  393.    GoToXY(12,1);
  394.    WRITE(' PibTerm Editor ');
  395.  
  396.    IF ( LENGTH( EditFileName ) > 0 ) THEN
  397.       BEGIN
  398.  
  399.          Split_File_Name( EditFileName, Drive, Path, FileN, FileT, BadF );
  400.  
  401.          GoToXY(31,1);
  402.  
  403.          WRITE(' ',FileN, '.',FileT,' ')
  404.  
  405.       END;
  406.                                    (* Display function key definitions *)
  407.    DisplayKeys;
  408.  
  409.    TextColor( ForeGround_Color );
  410.                                    (* Start at top of file             *)
  411.    CurrentLine := 1;
  412.    Column      := 1;
  413.    ScreenLine  := 1;
  414.    HighestLine := 1;
  415.  
  416.    EmptyLine^   := '';
  417.    SearchString := '';
  418.    Replacement  := '';
  419.                                    (* Set up tab stops at usual PC places *)
  420.    FOR I := 1 TO MaxECol DO
  421.       TabSet[I] := ( ( I MOD 8 ) = 1 );
  422.  
  423.                                    (* General purpose empty line          *)
  424.    NewBuffer( EmptyLine );
  425.                                    (* Figure # of lines fitting in our space *)
  426.  
  427.    IntMaxLines := MIN( MaxLines , TRUNC( ( MaxBlockAvail - 4096.0 ) / 100.0 ) );
  428.  
  429.    IF ( IntMaxLines <= 1 ) THEN
  430.       BEGIN
  431.          WRITELN;
  432.          Edit_Press_Any(' There isn''t enough memory to do any editing.');
  433.          Initialize := FALSE;
  434.       END
  435.    ELSE
  436.       BEGIN
  437.                                    (* Get space for line pointers      *)
  438.  
  439.          GETMEM( LineBuffer , SIZEOF( LinePtr ) * IntMaxLines );
  440.  
  441.                                    (* Initialize line pointers to empty *)
  442.  
  443.          FOR I := 1 TO IntMaxLines DO
  444.             LineBuffer^[I] := EmptyLine;
  445.  
  446.          GoToXY( 10 , 20 );
  447.                                    (* Read in file to be edited, if any *)
  448.  
  449.          Initialize := LoadFile( Name );
  450.  
  451.       END;
  452.  
  453. END   (* Initialize *);
  454.  
  455. (*----------------------------------------------------------------------*)
  456. (*                     Help --- provide help screen                     *)
  457. (*----------------------------------------------------------------------*)
  458.  
  459. PROCEDURE Help;
  460.  
  461. CONST
  462.    MaxHelpPage = 2;
  463.  
  464. VAR
  465.    Ch        : CHAR;
  466.    HPage     : INTEGER;
  467.    Help_Done : BOOLEAN;
  468.  
  469. (*----------------------------------------------------------------------*)
  470.  
  471. PROCEDURE Help1;
  472.  
  473. BEGIN (* Help1 *)
  474.  
  475.    Quick_Display( 5,  3,  'Character left        ^S    Left arrow');
  476.    Quick_Display( 5,  4,  'Character right       ^D    Right arrow');
  477.    Quick_Display( 5,  5,  'Word left             ^A    Ctrl left arrow');
  478.    Quick_Display( 5,  6,  'Word right            ^F    Ctrl right arrow');
  479.    Quick_Display( 5,  7,  'Left end of line      ^Q    Home');
  480.    Quick_Display( 5,  8,  'Right end of line     ^R    End');
  481.    Quick_Display( 5,  9,  'Line up               ^E    Up arrow');
  482.    Quick_Display( 5, 10,  'Line down             ^X    Down arrow');
  483.    Quick_Display( 5, 11,  'Page up               ^W    PgUp');
  484.    Quick_Display( 5, 12,  'Page down             ^Z    PgDn');
  485.    Quick_Display( 5, 13,  'Top of file           ^O    Ctrl PgUp');
  486.    Quick_Display( 5, 14,  'Bottom of file        ^L    Ctrl PgDn');
  487.  
  488.    Quick_Display( 5, 16,  'Insert mode on/off    ^V    Ins');
  489.    Quick_Display( 5, 17,  'Delete char at cursor ^G    Del');
  490.    Quick_Display( 5, 18,  'Delete left character ^H    BackSpace');
  491.  
  492.    Quick_Display( 5, 20,  'Control char prefix   ^P');
  493.  
  494. END   (* Help1 *);
  495.  
  496. (*----------------------------------------------------------------------*)
  497.  
  498. PROCEDURE Help2;
  499.  
  500. BEGIN (* Help2 *)
  501.  
  502.    Quick_Display( 5,  3,  'Display help          ^K1   F1');
  503.    Quick_Display( 5,  4,  'Locate string         ^K2   F2');
  504.    Quick_Display( 5,  5,  'Search for a string   ^K3   F3');
  505.    Quick_Display( 5,  6,  'Search and replace    ^K4   F4');
  506.    Quick_Display( 5,  7,  'Save file and quit    ^K5   F5');
  507.    Quick_Display( 5,  8,  'Insert blank line     ^K6   F6');
  508.    Quick_Display( 5,  9,  'Delete line           ^K7   F7');
  509.    Quick_Display( 5, 10,  'Quit without saving   ^K0   F10');
  510.  
  511. END   (* Help2 *);
  512.  
  513. (*----------------------------------------------------------------------*)
  514.  
  515. BEGIN (* Help *)
  516.                                    (* Help page one *)
  517.    HPage     := 1;
  518.                                    (* Help not done yet *)
  519.    Help_Done := FALSE;
  520.                                    (* Loop over help pages *)
  521.    REPEAT
  522.                                    (* Set window size *)
  523.  
  524.       Window( 1, 2, Max_Screen_Col, SUCC( Page_Size ) );
  525.  
  526.                                    (* Clear edit screen *)
  527.       Clear_Window;
  528.                                    (* Display help text *)
  529.  
  530.       Quick_Display( 15, 1, 'PibTerm Editor Help, page ' + IToS( HPage ) );
  531.  
  532.       CASE HPage OF
  533.          1:   Help1;
  534.          2:   Help2;
  535.          ELSE ;
  536.       END (* CASE *);
  537.  
  538.       Window( 1 , 1 , Max_Screen_Col , Max_Screen_Line );
  539.       GoToXY( 1 , Max_Screen_Line );
  540.       ClrEol;
  541.                                    (* Wait for key to be pressed *)
  542.  
  543.       WRITE('Hit ESC to return to editing or Enter for next help screen');
  544.  
  545.       Read_Kbd( Ch );
  546.  
  547.       IF ( Ch <> CHR( ESC ) ) THEN
  548.          BEGIN
  549.             HPage := SUCC( HPage );
  550.             IF ( HPage > MaxHelpPage ) THEN
  551.                HPage := 1;
  552.          END
  553.       ELSE
  554.          Help_Done := TRUE;
  555.  
  556.    UNTIL ( Help_Done );
  557.                                    (* Redisplay function keys and *)
  558.                                    (* redraw screen display       *)
  559.    DisplayKeys;
  560.    DrawScreen;
  561.  
  562. END   (* Help *);
  563.  
  564. (*----------------------------------------------------------------------*)
  565. (*         PrintRow --- Update status Line with new row/column          *)
  566. (*----------------------------------------------------------------------*)
  567.  
  568. PROCEDURE PrintRow;
  569.  
  570. BEGIN (* PrintRow *)
  571.                                    (* Display revised Line *)
  572.  
  573.    Window( 1 , 1 , Max_Screen_Col , Max_Screen_Line );
  574.  
  575.    TextColor( Menu_Text_Color );
  576.  
  577.    GoToXY( 54 , 1 );
  578.    WRITE(' Line ', CurrentLine : 4,' ');
  579.  
  580.                                    (* Display revised row *)
  581.    GoToXY( 68 , 1 );
  582.    WRITE(' Col ', Column : 2,' ');
  583.    Window( 1, 2, Max_Screen_Col, SUCC( Page_Size ) );
  584.  
  585.    TextColor( ForeGround_Color );
  586.  
  587. END   (* PrintRow *);
  588.  
  589. (*----------------------------------------------------------------------*)
  590. (*                GetKey --- Read keyboard input                        *)
  591. (*----------------------------------------------------------------------*)
  592.  
  593. FUNCTION GetKey( VAR SecNum: BOOLEAN;
  594.                  VAR InKey:  CHAR    ): BOOLEAN;
  595.  
  596. (* STRUCTURED *) CONST
  597.    Digits : SET OF '0'..'9' = ['0'..'9'];
  598.  
  599. BEGIN (* GetKey *)
  600.  
  601.    IF KeyPressed THEN
  602.       BEGIN
  603.  
  604.          READ( Kbd , InKey);
  605.          SecNum := ( InKey = CHR( ESC ) ) AND KeyPressed;
  606.  
  607.          IF SecNum THEN
  608.             BEGIN
  609.                READ( Kbd , Ch );
  610.                KeyNum := ORD( Ch ) + 128;
  611.             END
  612.          ELSE
  613.             IF ( ORD( InKey ) <= ESC ) THEN
  614.                BEGIN
  615.                   SecNum := TRUE;
  616.                   KeyNum := ORD(InKey);
  617.                   IF ( InKey = ^K ) THEN
  618.                      BEGIN
  619.                         Read_Kbd( Ch );
  620.                         IF ( Ch IN Digits ) THEN
  621.                            IF ( Ch <> '0' ) THEN
  622.                               KeyNum := F1 + ORD( Ch ) - ORD( '0' ) + 128
  623.                            ELSE
  624.                               KeyNum := F10 + 128
  625.                         ELSE
  626.                            Menu_Beep;
  627.                      END
  628.                   ELSE IF ( InKey = ^P ) THEN
  629.                      BEGIN
  630.                         Read_Kbd( Ch );
  631.                         SecNum := FALSE;
  632.                         KeyNum := ORD( InKey );
  633.                      END;
  634.                END
  635.             ELSE
  636.                BEGIN
  637.                   KeyNum := ORD(InKey);
  638.                   SecNum := FALSE;
  639.                END
  640.       END
  641.    ELSE
  642.       BEGIN
  643.          GetKey := FALSE;
  644.          SecNum := FALSE;
  645.       END;
  646.  
  647. END   (* GetKey *);
  648.  
  649. (*----------------------------------------------------------------------*)
  650. (*              Character --- Insert Character at current pos in Line   *)
  651. (*----------------------------------------------------------------------*)
  652.  
  653. PROCEDURE Character;
  654.  
  655. BEGIN (* Character *)
  656.                                    (* See if room to Insert a character *)
  657.  
  658.    IF ( Column = PRED( MaxECol ) ) THEN
  659.  
  660.       Menu_Beep                    (* No room -- sound bell *)
  661.    ELSE
  662.       BEGIN
  663.                                    (* Room -- display character at current *)
  664.                                    (* screen position                      *)
  665.  
  666.          GoToXY( Column , ScreenLine );
  667.          WRITE( InKey );
  668.                                    (* Update line buffer pointer and text  *)
  669.                                    (* line itself.                         *)
  670.  
  671.          IF ( LineBuffer^[CurrentLine] = EmptyLine ) THEN
  672.             BEGIN
  673.                NewBuffer(LineBuffer^[CurrentLine]);
  674.                LineBuffer^[CurrentLine]^ := '';
  675.             END;
  676.                                     (* Append any blanks needed            *)
  677.  
  678.          WHILE ( LENGTH(LineBuffer^[CurrentLine]^) < Column ) DO
  679.             LineBuffer^[CurrentLine]^ := LineBuffer^[CurrentLine]^ + ' ';
  680.  
  681.                                    (* Insert character in Line             *)
  682.  
  683.          Insert(InKey, LineBuffer^[CurrentLine]^, Column);
  684.  
  685.                                    (* Update column positions *)
  686.          Column := SUCC( Column );
  687.                                    (* If not insert mode, delete character *)
  688.  
  689.          IF ( NOT InsertMode ) THEN
  690.             Delete(LineBuffer^[CurrentLine]^, Column, 1);
  691.  
  692.                                    (* Redraw current Line if Insert mode active *)
  693.          IF InsertMode THEN
  694.             Quick_Display( 1 , ScreenLine , LineBuffer^[CurrentLine]^ );
  695.  
  696.                                    (* Ring bell when close to end of a Line *)
  697.          IF ( Column = 70 ) THEN
  698.             Menu_Beep;
  699.  
  700.       END;
  701.  
  702. END   (* Character *);
  703.  
  704. (*----------------------------------------------------------------------*)
  705. (*                 BeginFile --- Move to top of file                    *)
  706. (*----------------------------------------------------------------------*)
  707.  
  708. PROCEDURE BeginFile;
  709.  
  710. BEGIN (* BeginFile *)
  711.                                    (* Reset Line pointers to top of file *)
  712.    CurrentLine := 1;
  713.    Column      := 1;
  714.    ScreenLine  := 1;
  715.  
  716.    FirstColumn := 1;
  717.    LastColumn  := 80;
  718.                                    (* Display lines at top of file      *)
  719.    DrawScreen;
  720.  
  721. END   (* BeginFile *);
  722.  
  723. (*----------------------------------------------------------------------*)
  724. (*                 EndFile --- Move to end of file                      *)
  725. (*----------------------------------------------------------------------*)
  726.  
  727. PROCEDURE EndFile;
  728.  
  729. BEGIN (* EndFile *)
  730.                                    (* Reset Line pointers to end of file *)
  731.  
  732.    CurrentLine := HighestLine;
  733.    ScreenLine  := MIN( HighestLine , 12 );
  734.    Column      := 1;
  735.                                    (* Display lines at end of file       *)
  736.    DrawScreen;
  737.  
  738. END   (* EndFile *);
  739.  
  740. (*----------------------------------------------------------------------*)
  741. (*                 FuncEnd --- Move to end of current Line              *)
  742. (*----------------------------------------------------------------------*)
  743.  
  744. PROCEDURE FuncEnd;
  745.  
  746. BEGIN (* FuncEnd *)
  747.  
  748.    Column := MIN( LENGTH( LineBuffer^[CurrentLine]^ ) + 1 , MaxECol );
  749.  
  750. END   (* FuncEnd *);
  751.  
  752. (*----------------------------------------------------------------------*)
  753. (*                CursorUp --- Move up one Line in file/screen          *)
  754. (*----------------------------------------------------------------------*)
  755.  
  756. PROCEDURE CursorUp;
  757.  
  758. VAR
  759.    Count: INTEGER;
  760.  
  761. BEGIN (* CursorUp *)
  762.                                    (* Do nothing if already at top of file *)
  763.    IF ( CurrentLine <= 1 ) THEN
  764.       EXIT;
  765.                                    (* Move back one Line in file; if at top *)
  766.                                    (* line on screen, perform scroll down   *)
  767.  
  768.    CurrentLine := PRED( CurrentLine );
  769.  
  770.    IF ( ScreenLine = 1 ) THEN
  771.       BEGIN
  772.          GoToXY( 1 , 1 );
  773.          InsLine;
  774.          Quick_Display( 1, 1, LineBuffer^[CurrentLine]^ );
  775.       END
  776.    ELSE
  777.       ScreenLine := PRED( ScreenLine );
  778.  
  779. END   (* CursorUp *);
  780.  
  781. (*----------------------------------------------------------------------*)
  782. (*            CursorDown --- Move down one Line in file/screen          *)
  783. (*----------------------------------------------------------------------*)
  784.  
  785. PROCEDURE CursorDown;
  786.  
  787. BEGIN (* CursorDown *)
  788.                                    (* Down arrow doesn't move past EOF *)
  789.  
  790.    IF ( CurrentLine >= HighestLine ) THEN EXIT;
  791.  
  792.                                    (* Increment Line counter *)
  793.  
  794.    CurrentLine := SUCC( CurrentLine );
  795.  
  796.                                    (* Increment screen Line counter *)
  797.  
  798.    ScreenLine  := SUCC( ScreenLine );
  799.  
  800.                                    (* If at last Line on screen, perform *)
  801.                                    (* scroll up.                         *)
  802.  
  803.    IF ( ScreenLine > Page_Size ) THEN
  804.       BEGIN
  805.          GoToXY(1, 1);
  806.          DelLine;
  807.          ScreenLine := Page_Size;
  808.          Quick_Display( 1 , ScreenLine , LineBuffer^[CurrentLine]^ );
  809.       END;
  810.  
  811. END   (* CursorDown *);
  812.  
  813. (*----------------------------------------------------------------------*)
  814. (*            InsertLine --- Insert one Line in file/screen             *)
  815. (*----------------------------------------------------------------------*)
  816.  
  817. PROCEDURE InsertLine;
  818.  
  819. BEGIN (* InsertLine *)
  820.                                    (* Insert Line on screen *)
  821.    InsLine;
  822.                                    (* Move Line pointers up a slot *)
  823.  
  824.    FOR I := SUCC( HighestLine ) DOWNTO CurrentLine DO
  825.       LineBuffer^[SUCC(I)] := LineBuffer^[I];
  826.  
  827.                                    (* Make new Line empty *)
  828.  
  829.    LineBuffer^[CurrentLine] := EmptyLine;
  830.  
  831.                                    (* Increment Line count *)
  832.  
  833.    HighestLine              := SUCC( HighestLine );
  834.  
  835. END   (* InsertLine *);
  836.  
  837. (*----------------------------------------------------------------------*)
  838. (*                Enter --- handle enter key pressed                    *)
  839. (*----------------------------------------------------------------------*)
  840.  
  841. PROCEDURE Enter;
  842.  
  843. VAR
  844.    LTemp : AnyStr;
  845.    RTemp : AnyStr;
  846.    L     : INTEGER;
  847.  
  848. BEGIN (* Enter *)
  849.                                    (* If insert mode active, split line *)
  850.                                    (* at current column position.       *)
  851.    IF InsertMode THEN
  852.       BEGIN
  853.                                    (* Get characters up to marked column *)
  854.  
  855.          LTemp := Substr( LineBuffer^[CurrentLine]^, 1, PRED( Column ) );
  856.  
  857.          L := LENGTH( LineBuffer^[CurrentLine]^ );
  858.  
  859.                                    (* Get remaining characters -- these *)
  860.                                    (* form the next line.               *)
  861.  
  862.          RTemp := Substr( LineBuffer^[CurrentLine]^, Column, L - Column + 1 );
  863.  
  864.                                    (* Update first Line *)
  865.  
  866.          LineBuffer^[CurrentLine]^ := LTemp;
  867.  
  868.                                     (* Make room for new Line *)
  869. {        CursorDown; }
  870.                                    (* Increment Line counter *)
  871.  
  872.          CurrentLine := SUCC( CurrentLine );
  873.  
  874.                                    (* Increment screen Line counter *)
  875.  
  876.          ScreenLine  := SUCC( ScreenLine );
  877.  
  878.                                    (* If at last Line on screen, perform *)
  879.                                    (* scroll up.                         *)
  880.  
  881.          IF ( ScreenLine > Page_Size ) THEN
  882.             BEGIN
  883.                GoToXY( 1 ,  1 );
  884.                DelLine;
  885.                ScreenLine := Page_Size;
  886.                Quick_Display( 1 , ScreenLine , LineBuffer^[CurrentLine]^ );
  887.             END;
  888.  
  889.          InsertLine;
  890.                                     (* Allocate space for new Line *)
  891.  
  892.          NewBuffer(LineBuffer^[CurrentLine]);
  893.  
  894.                                     (* New Line is second half of old Line *)
  895.  
  896.          LineBuffer^[CurrentLine]^ := RTemp;
  897.  
  898.                                    (* Display revised lines *)
  899.          DrawScreen;
  900.  
  901.       END
  902.    ELSE                            (* If replace mode, move to next Line *)
  903.       CursorDown;
  904.  
  905.    Column := 1;
  906.    GoToXY( Column , ScreenLine );
  907.  
  908. END   (* Enter *);
  909.  
  910. (*----------------------------------------------------------------------*)
  911. (*                   DeleteLine --- Delete a Line                       *)
  912. (*----------------------------------------------------------------------*)
  913.  
  914. PROCEDURE DeleteLine;
  915.  
  916. BEGIN (* DeleteLine *)
  917.                                    (* If no current lines, do nothing. *)
  918.  
  919.    IF ( HighestLine = 0 ) THEN EXIT;
  920.  
  921.                                    (* Delete current line on screen *)
  922.    DelLine;
  923.                                    (* Move up lines below it to fill in *)
  924.  
  925.    IF ( HighestLine > CurrentLine + ( Page_Size + 1 - ScreenLine ) ) THEN
  926.       Quick_Display( 1 , Page_Size ,
  927.                      LineBuffer^[ CurrentLine + ( Page_Size + 1 - ScreenLine ) ]^ );
  928.  
  929.                                    (* Make this line empty *)
  930.  
  931.    ZapBuffer( LineBuffer^[CurrentLine] );
  932.  
  933.                                    (* Move down higher line pointers *)
  934.  
  935.    FOR I := CurrentLine TO HighestLine DO
  936.       LineBuffer^[I] := LineBuffer^[SUCC(I)];
  937.  
  938.                                    (* Empty out former last line in file *)
  939.  
  940.    ZapBuffer( LineBuffer^[HighestLine] );
  941.  
  942.                                    (* Drop Line count *)
  943.  
  944.    HighestLine := PRED( HighestLine );
  945.  
  946.                                    (* Reset current line if > new last line *)
  947.  
  948.    IF ( CurrentLine > HighestLine ) THEN
  949.       CursorUp;
  950.  
  951. END   (* DeleteLine *);
  952.  
  953. (*----------------------------------------------------------------------*)
  954. (*                   CursorLeft --- Move one column to left             *)
  955. (*----------------------------------------------------------------------*)
  956.  
  957. PROCEDURE CursorLeft;
  958.  
  959. BEGIN (* CursorLeft *)
  960.                                    (* Move one column to left *)
  961.    Column := PRED( Column );
  962.                                    (* Move to previous Line if ran off *)
  963.                                    (* left end of current line.        *)
  964.    IF ( Column < 1 ) THEN
  965.       BEGIN
  966.          CursorUp;
  967.          FuncEnd;
  968.       END;
  969.  
  970. END   (* CursorLeft *);
  971.  
  972. (*----------------------------------------------------------------------*)
  973. (*                CursorRight --- Move one column to right              *)
  974. (*----------------------------------------------------------------------*)
  975.  
  976. PROCEDURE CursorRight;
  977.  
  978. BEGIN (* CursorRight *)
  979.                                    (* Move forward one column *)
  980.    Column := SUCC( Column );
  981.                                    (* Move to next Line if needed *)
  982.  
  983.    IF ( Column > PRED( MaxECol ) ) THEN
  984.       BEGIN
  985.          CursorDown;
  986.          Column := 1;
  987.       END;
  988.  
  989. END   (* CursorRight *);
  990.  
  991. (*----------------------------------------------------------------------*)
  992. (*                Ins --- Toggle insert/overwrite mode                  *)
  993. (*----------------------------------------------------------------------*)
  994.  
  995. PROCEDURE Ins;
  996.  
  997. BEGIN (* Ins *)
  998.                                    (* Flip insert/overwrite mode *)
  999.  
  1000.    InsertMode := ( NOT InsertMode );
  1001.  
  1002.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1003.    GoToXY( 1 , 1 );
  1004.                                    (* Update status display      *)
  1005.    TextColor( Menu_Text_Color );
  1006.  
  1007.    IF InsertMode THEN
  1008.       BEGIN
  1009.          WRITE( 'Insert ' );
  1010.          TextColor( Menu_Frame_Color );
  1011.          WRITE( CHR( 205 ) );
  1012.       END
  1013.    ELSE
  1014.       WRITE('Replace');
  1015.  
  1016.    Window( 1, 2, Max_Screen_Col, SUCC( Page_Size ) );
  1017.  
  1018.    TextColor( ForeGround_Color );
  1019.  
  1020. END   (* Ins *);
  1021.  
  1022. (*----------------------------------------------------------------------*)
  1023. (*                     Del --- Delete a character                       *)
  1024. (*----------------------------------------------------------------------*)
  1025.  
  1026. PROCEDURE Del;
  1027.  
  1028. BEGIN (* Del *)
  1029.                                    (* Join following Line to current Line *)
  1030.                                    (* if delete past end of Line          *)
  1031.  
  1032.    IF ( Column > LENGTH(LineBuffer^[CurrentLine]^) ) THEN
  1033.       BEGIN
  1034.          IF ( ( LENGTH(LineBuffer^[CurrentLine]^ ) +
  1035.                 LENGTH(LineBuffer^[CurrentLine+1]^ ) ) < MaxECol ) THEN
  1036.             BEGIN
  1037.  
  1038.                LineBuffer^[CurrentLine]^ := LineBuffer^[CurrentLine]^ +
  1039.                                            LineBuffer^[CurrentLine+1]^;
  1040.  
  1041.                Quick_Display( 1, ScreenLine, LineBuffer^[CurrentLine]^ );
  1042.                CursorDown;
  1043.                DeleteLine;
  1044.                CursorUp;
  1045.                DrawScreen;
  1046.             END
  1047.          ELSE
  1048.             WRITE( CHR( BELL ) );
  1049.          EXIT;
  1050.       END;
  1051.                                    (* Line already empty *)
  1052.  
  1053.    IF ( LineBuffer^[CurrentLine] = EmptyLine ) THEN
  1054.       BEGIN
  1055.          NewBuffer(LineBuffer^[CurrentLine]);
  1056.          LineBuffer^[CurrentLine]^ := '';
  1057.       END;
  1058.                                    (* Append blanks as needed *)
  1059.  
  1060.    WHILE ( LENGTH(LineBuffer^[CurrentLine]^) < Column ) DO
  1061.       LineBuffer^[CurrentLine]^ := LineBuffer^[CurrentLine]^ + ' ';
  1062.  
  1063.                                    (* Delete character from text Line *)
  1064.  
  1065.    Ch := COPY( LineBuffer^[CurrentLine]^, Column, 1 );
  1066.    DELETE( LineBuffer^[CurrentLine]^, Column, 1 );
  1067.  
  1068.                                    (* Redisplay updated Line *)
  1069.    GoToXY(1,ScreenLine);
  1070.    ClrEol;
  1071.  
  1072.    Quick_Display( 1 , ScreenLine , LineBuffer^[CurrentLine]^ );
  1073.  
  1074. END   (* Del *);
  1075.  
  1076. (*----------------------------------------------------------------------*)
  1077. (*       BackSpace --- Move left and possibly delete character          *)
  1078. (*----------------------------------------------------------------------*)
  1079.  
  1080. PROCEDURE BackSpace;
  1081.  
  1082. BEGIN (* BackSpace *)
  1083.                                    (* Move one column to left *)
  1084.    Column := PRED( Column );
  1085.                                    (* Move to previous Line if ran off *)
  1086.                                    (* left end of current line.        *)
  1087.    IF ( Column < 1 ) THEN
  1088.       BEGIN
  1089.          CursorUp;
  1090.          FuncEnd;
  1091.       END;
  1092.                                    (* Delete character *)
  1093.    Del;
  1094.  
  1095. END   (* BackSpace *);
  1096.  
  1097. (*----------------------------------------------------------------------*)
  1098. (*                  Terminate --- End editing session                   *)
  1099. (*----------------------------------------------------------------------*)
  1100.  
  1101. PROCEDURE Terminate;
  1102.  
  1103. VAR
  1104.    HoldName : AnyStr;
  1105.    Dot_Pos  : INTEGER;
  1106.    F        : FILE;
  1107.    I        : INTEGER;
  1108.  
  1109. BEGIN  (* Terminate *)
  1110.                                    (* Remove status lines *)
  1111.  
  1112.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1113.    GoToXY( 1, Max_Screen_Line );
  1114.    ClrEol;
  1115.    GoToXY( 1, PRED( Max_Screen_Line ) );
  1116.    ClrEol;
  1117.                                    (* Bring up write window *)
  1118.  
  1119.    Save_Partial_Screen( Local_Save, 5, 10, 75, 15 );
  1120.  
  1121.    Draw_Menu_Frame( 5, 10, 75, 15, Menu_Frame_Color, Menu_Title_Color,
  1122.                     Menu_Text_Color, 'Write file ' );
  1123.  
  1124.                                    (* Pick up file name if none given *)
  1125.    IF ( EditFileName = '' ) THEN
  1126.       BEGIN
  1127.          WRITELN(' Enter file name to write to: ');
  1128.          WRITE(' >');
  1129.          Read_Edited_String( EditFileName );
  1130.          WRITELN;
  1131.       END
  1132.    ELSE
  1133.                                    (* Get .BAK form of name *)
  1134.       BEGIN
  1135.  
  1136.          HoldName := EditFileName;
  1137.  
  1138.          Dot_Pos  := POS( '.' , HoldName );
  1139.  
  1140.          IF ( Dot_Pos = 0 ) THEN
  1141.             HoldName := HoldName + '.BAK'
  1142.          ELSE
  1143.             HoldName := COPY( HoldName, 1, Dot_Pos ) + 'BAK';
  1144.  
  1145.                                    (* Erase any previous .BAK file *)
  1146.             (*$I-*)
  1147.          ASSIGN( F , HoldName );
  1148.          RESET ( F );
  1149.             (*$I+*)
  1150.  
  1151.          IF ( INT24Result = 0 ) THEN
  1152.             BEGIN
  1153.                CLOSE( F );
  1154.                ERASE( F );
  1155.             END;
  1156.                                    (* Rename old version as *.BAK *)
  1157.             (*$I-*)
  1158.          RENAME( TextFile , HoldName );
  1159.             (*$I+*)
  1160.          I := INT24RESULT;
  1161.  
  1162.       END;
  1163.                                    (* Write the edited version *)
  1164.    WRITE(' Writing Line ');
  1165.    ClrEol;
  1166.  
  1167.    ASSIGN ( TextFile , EditFileName );
  1168.    REWRITE( TextFile );
  1169.  
  1170.    FOR I := 1 TO HighestLine DO
  1171.       BEGIN
  1172.  
  1173.          IF ( ( I MOD 25 ) = 0 ) THEN
  1174.             BEGIN
  1175.                GoToXY( 15 , WhereY );
  1176.                WRITE( I );
  1177.             END;
  1178.  
  1179.          WRITELN(TextFile, LineBuffer^[I]^);
  1180.  
  1181.       END;
  1182.  
  1183.    GoToXY( 15 , WhereY );
  1184.    WRITE( I );
  1185.    WRITELN;
  1186.  
  1187.       (*$I-*)
  1188.    CLOSE  ( TextFile );
  1189.       (*$I+*)
  1190.  
  1191.    Edit_Press_Any(' File written.  Press any key to exit ...');
  1192.  
  1193.                                    (* Editing done *)
  1194.    Edit_Done := TRUE;
  1195.  
  1196.    Restore_Screen( Local_Save );
  1197.    Reset_Global_Colors;
  1198.  
  1199. END;
  1200.  
  1201. (*----------------------------------------------------------------------*)
  1202. (*         QuitNoSave --- End editor session without saving file        *)
  1203. (*----------------------------------------------------------------------*)
  1204.  
  1205. PROCEDURE QuitNoSave;
  1206.  
  1207. BEGIN (* QuitNoSave *)
  1208.  
  1209.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1210.    GoToXY( 1, Max_Screen_Line );
  1211.    ClrEol;
  1212.  
  1213.    GoToXY( 1, PRED( Max_Screen_Line ) );
  1214.    ClrEol;
  1215.  
  1216.    Edit_Done := TRUE;
  1217.  
  1218. END   (* QuitNoSave *);
  1219.  
  1220. (*----------------------------------------------------------------------*)
  1221. (*                  FuncPgUp --- move up one screenful in file          *)
  1222. (*----------------------------------------------------------------------*)
  1223.  
  1224. PROCEDURE FuncPgUp;
  1225.  
  1226. BEGIN (* FuncPgUp *)
  1227.                                    (* Back up one screen in file *)
  1228.  
  1229.    CurrentLine := CurrentLine - Page_Size;
  1230.  
  1231.                                    (* If backed up past start of file, *)
  1232.                                    (* display start of file.           *)
  1233.  
  1234.    IF ( CurrentLine <= ScreenLine ) THEN
  1235.       BeginFile
  1236.    ELSE
  1237.       DrawScreen;
  1238.  
  1239. END   (* FuncPgUp *);
  1240.  
  1241. (*----------------------------------------------------------------------*)
  1242. (*                FuncPgDn --- move down one screenful in file          *)
  1243. (*----------------------------------------------------------------------*)
  1244.  
  1245. PROCEDURE FuncPgDn;
  1246.  
  1247. BEGIN (* FuncPgDn *)
  1248.                                    (* Move forward one page in file *)
  1249.  
  1250.    CurrentLine := CurrentLine + Page_Size;
  1251.  
  1252.                                    (* If past end of file, display *)
  1253.                                    (* end of file.                 *)
  1254.  
  1255.    IF ( ( CurrentLine + 12 ) >= HighestLine ) THEN
  1256.       EndFile
  1257.    ELSE
  1258.       DrawScreen;
  1259.  
  1260. END   (* FuncPgDn *);
  1261.  
  1262. (*----------------------------------------------------------------------*)
  1263. (*                  PrevWord --- move left one word in file             *)
  1264. (*----------------------------------------------------------------------*)
  1265.  
  1266. PROCEDURE PrevWord;
  1267.  
  1268. BEGIN (* PrevWord *)
  1269.  
  1270.                                    (* If in word move to space *)
  1271.  
  1272.    WHILE ( NOT ( ( LineBuffer^[CurrentLine]^[Column] = ' ' ) OR
  1273.                ( Column >= LENGTH(LineBuffer^[CurrentLine]^) ) ) ) AND
  1274.          ( ( CurrentLine <> 1 ) OR ( Column <> 1 ) ) DO
  1275.       CursorLeft;
  1276.  
  1277.                                   (* Find end of previous word *)
  1278.  
  1279.    WHILE ( ( LineBuffer^[CurrentLine]^[Column] = ' ' ) OR
  1280.            ( Column >= LENGTH(LineBuffer^[CurrentLine]^) ) ) AND
  1281.          ( ( CurrentLine <> 1 ) OR ( Column <> 1 ) ) DO
  1282.       CursorLeft;
  1283.                                  (* Find start of previous word *)
  1284.  
  1285.    WHILE ( NOT ( ( LineBuffer^[CurrentLine]^[Column] = ' ' ) OR
  1286.                ( Column >= LENGTH(LineBuffer^[CurrentLine]^) ) ) ) AND
  1287.          ( ( CurrentLine <> 1 ) OR ( Column <> 1 ) ) DO
  1288.       CursorLeft;
  1289.  
  1290.                                  (* Position to start of previous word *)
  1291.    CursorRight;
  1292.  
  1293. END   (* PrevWord *);
  1294.  
  1295. (*----------------------------------------------------------------------*)
  1296. (*              NextWord --- Move forward in Line one word              *)
  1297. (*----------------------------------------------------------------------*)
  1298.  
  1299. PROCEDURE NextWord;
  1300.  
  1301. BEGIN (* NextWord *)
  1302.  
  1303.                                    (* If in word, move to the whitespace *)
  1304.  
  1305.    WHILE ( NOT ( ( LineBuffer^[CurrentLine]^[Column] = ' ' ) OR
  1306.                ( Column >= LENGTH( LineBuffer^[CurrentLine]^ ) ) ) ) AND
  1307.          ( CurrentLine < HighestLine ) DO
  1308.       CursorRight;
  1309.  
  1310.                                    (* Skip over space to next word *)
  1311.  
  1312.    WHILE ( ( LineBuffer^[CurrentLine]^[Column] = ' ' ) OR
  1313.            ( Column >= LENGTH(LineBuffer^[CurrentLine]^) ) ) AND
  1314.          ( CurrentLine < HighestLine ) DO
  1315.       CursorRight;
  1316.  
  1317. END   (* NextWord *);
  1318.  
  1319. (*----------------------------------------------------------------------*)
  1320. (*              Tab --- Move forwards in Line one tab stop              *)
  1321. (*----------------------------------------------------------------------*)
  1322.  
  1323. PROCEDURE Tab;
  1324.  
  1325. BEGIN (* Tab *)
  1326.  
  1327.    IF ( Column < PRED( MaxECol ) ) THEN
  1328.       REPEAT
  1329.          Column := Column + 1;
  1330.       UNTIL ( TabSet[Column] ) OR ( Column = PRED( MaxECol ) );
  1331.  
  1332. END   (* Tab *);
  1333.  
  1334. (*----------------------------------------------------------------------*)
  1335. (*            BackTab --- Move backwards in Line one tab stop           *)
  1336. (*----------------------------------------------------------------------*)
  1337.  
  1338. PROCEDURE BackTab;
  1339.  
  1340. BEGIN (* BackTab *)
  1341.  
  1342.    IF ( Column > 1 ) THEN
  1343.       REPEAT
  1344.          Column := PRED( Column );
  1345.       UNTIL ( TabSet[Column] ) OR ( Column <= 1 );
  1346.  
  1347. END   (* BackTab *);
  1348.  
  1349. (*----------------------------------------------------------------------*)
  1350. (*            Esc --- Handle escape key (clear current line)            *)
  1351. (*----------------------------------------------------------------------*)
  1352.  
  1353. PROCEDURE Esc_Key;
  1354.  
  1355. BEGIN (* Esc_Key *)
  1356.                                    (* Move to column one of current Line *)
  1357.    Column := 1;
  1358.    GoToXY(1, WhereY);
  1359.                                    (* Clear it *)
  1360.    ClrEol;
  1361.                                    (* Make it empty *)
  1362.  
  1363.    ZapBuffer( LineBuffer^[CurrentLine] );
  1364.  
  1365. END   (* Esc_Key *);
  1366.  
  1367. (*----------------------------------------------------------------------*)
  1368. (*          Locate --- Locate all lines containing string               *)
  1369. (*----------------------------------------------------------------------*)
  1370.  
  1371. PROCEDURE Locate;
  1372.  
  1373. VAR
  1374.    Temp      : AnyStr;
  1375.    Pointer   : INTEGER;
  1376.    Position  : INTEGER;
  1377.    Line      : INTEGER;
  1378.    Len       : INTEGER;
  1379.  
  1380. BEGIN (* Locate *)
  1381.  
  1382.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1383.    GoToXY( 1, Max_Screen_Line );
  1384.    ClrEol;
  1385.  
  1386.    WRITE('Locate:     Enter string> ');
  1387.  
  1388.    Read_Edited_String( SearchString );
  1389.  
  1390.    Len := LENGTH( SearchString );
  1391.  
  1392.    IF ( Len = 0 ) THEN
  1393.       BEGIN
  1394.          DisplayKeys;
  1395.          BeginFile;
  1396.          EXIT;
  1397.       END;
  1398.  
  1399.    GoToXY(1, 25);
  1400.    ClrEol;
  1401.    WRITE('Searching...  Press <ESC> to exit, <SCROLL LCK> to pause');
  1402.  
  1403.    Window( 1, 2, Max_Screen_Col, SUCC( Page_Size ) );
  1404.    Clear_Window;
  1405.  
  1406.    FOR I := 1 TO HighestLine DO
  1407.       BEGIN
  1408.                                    (* look for matches on this Line *)
  1409.  
  1410.          Pointer := POS( SearchString, LineBuffer^[I]^ );
  1411.  
  1412.                                   (* If there was a match then get  *)
  1413.                                   (* ready to display it            *)
  1414.          IF ( Pointer > 0 ) THEN
  1415.             BEGIN
  1416.                Temp     := LineBuffer^[I]^;
  1417.                Position := Pointer;
  1418.                GoToXY( 1 , WhereY );
  1419.                TextColor( LightGray );
  1420.                WRITE( COPY( Temp, 1, PRED( MaxECol ) ) );
  1421.  
  1422.                                    (* Honor scroll lock *)
  1423.  
  1424.                WHILE( Scroll_Lock_On ) DO;
  1425.  
  1426.                                    (* print all of the matches on this Line *)
  1427.  
  1428.                WHILE ( Pointer > 0 ) DO
  1429.                   BEGIN
  1430.                      GoToXY(Position, WhereY);
  1431.                      WRITE( COPY( Temp, Pointer, Len ) );
  1432.                      Temp     := COPY( Temp, Pointer + Len + 1, 128);
  1433.                      Pointer  := POS( SearchString, Temp);
  1434.                      Position := Position + Pointer + Len;
  1435.                   END;
  1436.                                    (* go to next Line and keep searching *)
  1437.                WRITELN;
  1438.  
  1439.             END;
  1440.  
  1441.       END;
  1442.  
  1443.    TextColor( ForeGround_Color );
  1444.  
  1445.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1446.    GoToXY( 1 , Max_Screen_Line );
  1447.    ClrEol;
  1448.  
  1449.    Edit_Press_Any('End of Locate.  Press any key to exit ...');
  1450.  
  1451.                                    (* Display function keys *)
  1452.    DisplayKeys;
  1453.                                    (* Return to top of file *)
  1454.    BeginFile;
  1455.  
  1456.  END  (* Locate *);
  1457.  
  1458. (*----------------------------------------------------------------------*)
  1459. (*                   Search --- Search for string in text               *)
  1460. (*----------------------------------------------------------------------*)
  1461.  
  1462. PROCEDURE Search;
  1463.  
  1464. VAR
  1465.    Temp      : AnyStr;
  1466.    Pointer   : INTEGER;
  1467.    Position  : INTEGER;
  1468.    Line      : INTEGER;
  1469.    Len       : INTEGER;
  1470.  
  1471. BEGIN (* Search *)
  1472.  
  1473.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1474.    GoToXY( 1 , Max_Screen_Line );
  1475.    ClrEol;
  1476.  
  1477.    WRITE('Search:     Enter string> ');
  1478.  
  1479.    Read_Edited_String( SearchString );
  1480.  
  1481.    Len := LENGTH( SearchString );
  1482.  
  1483.    IF ( Len = 0 ) THEN
  1484.       BEGIN
  1485.          DisplayKeys;
  1486.          BeginFile;
  1487.          EXIT;
  1488.       END;
  1489.  
  1490.    GoToXY( 1 , Max_Screen_Line );
  1491.    ClrEol;
  1492.  
  1493.    WRITE('Searching...');
  1494.    Window( 1, 2, Max_Screen_Col, SUCC( Page_Size ) );
  1495.  
  1496.    FOR I := ( CurrentLine + 1 ) TO HighestLine DO
  1497.       BEGIN
  1498.                                    (* look FOR matches on this Line *)
  1499.  
  1500.          Pointer := POS( SearchString, LineBuffer^[I]^);
  1501.  
  1502.                                    (* IF there was a match THEN get *)
  1503.                                    (* ready to print it             *)
  1504.          IF ( Pointer > 0 ) THEN
  1505.             BEGIN
  1506.                CurrentLine := I;
  1507.                IF CurrentLine >= 12 THEN
  1508.                   ScreenLine := 12
  1509.                ELSE
  1510.                   ScreenLine := CurrentLine;
  1511.  
  1512.                DrawScreen;
  1513.                Column := Pointer;
  1514.  
  1515.                TextColor( LightGray );
  1516.  
  1517.                GoToXY(Column,ScreenLine);
  1518.                WRITE(SearchString);
  1519.  
  1520.                TextColor( ForeGround_Color );
  1521.  
  1522.                DisplayKeys;
  1523.  
  1524.                EXIT;
  1525.  
  1526.             END;
  1527.  
  1528.       END;
  1529.  
  1530.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1531.    GoToXY( 1 , Max_Screen_Line );
  1532.    ClrEol;
  1533.  
  1534.    Edit_Press_Any('Search string not found.  Press any key to exit ...');
  1535.  
  1536.    DisplayKeys;
  1537.  
  1538. END   (* Search *);
  1539.  
  1540. (*----------------------------------------------------------------------*)
  1541. (*                Replace --- Search for and replace string in text     *)
  1542. (*----------------------------------------------------------------------*)
  1543.  
  1544. PROCEDURE Replace;
  1545.  
  1546. VAR
  1547.    Temp      : AnyStr;
  1548.    Position  : INTEGER;
  1549.    Line      : INTEGER;
  1550.    Len       : INTEGER;
  1551.    S_Len     : INTEGER;
  1552.    Save_Pos  : INTEGER;
  1553.    L         : INTEGER;
  1554.    IPos      : INTEGER;
  1555.  
  1556. BEGIN (* Replace *)
  1557.  
  1558.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1559.    GoToXY( 1 , Max_Screen_Line );
  1560.    ClrEol;
  1561.  
  1562.    WRITE('Replace:     Enter search string> ');
  1563.  
  1564.    Read_Edited_String(SearchString);
  1565.  
  1566.    S_Len := LENGTH(SearchString);
  1567.  
  1568.    IF ( S_Len = 0 ) THEN
  1569.       BEGIN
  1570.          DisplayKeys;
  1571.          EXIT;
  1572.       END;
  1573.  
  1574.    GoToXY( 1 , Max_Screen_Line );
  1575.    ClrEol;
  1576.  
  1577.    WRITE('Replace:     Enter replacement string> ');
  1578.  
  1579.    Read_Edited_String(Replacement);
  1580.  
  1581.    Len := LENGTH( Replacement );
  1582.  
  1583.    GoToXY( 1 , Max_Screen_Line );
  1584.    ClrEol;
  1585.    WRITE('Searching...');
  1586.  
  1587.    Window( 1, 2, Max_Screen_Col, SUCC( Page_Size ) );
  1588.    Clear_Window;
  1589.  
  1590.    Choice := ' ';
  1591.  
  1592.    FOR Line := CurrentLine TO HighestLine DO
  1593.       BEGIN
  1594.  
  1595.          Position := POS( SearchString, LineBuffer^[Line]^ );
  1596.  
  1597.          WHILE( Position > 0 ) DO
  1598.             BEGIN
  1599.  
  1600.                CurrentLine := Line;
  1601.  
  1602.                IF ( CurrentLine >= 12 ) THEN
  1603.                   ScreenLine := 12
  1604.                ELSE
  1605.                   ScreenLine := CurrentLine;
  1606.  
  1607.                DrawScreen;
  1608.                Column := Position;
  1609.  
  1610.                TextColor( LightGray );
  1611.  
  1612.                GoToXY(Column,ScreenLine);
  1613.                WRITE(SearchString);
  1614.  
  1615.                TextColor( ForeGround_Color );
  1616.  
  1617.                Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1618.                GoToXY( 1 , Max_Screen_Line );
  1619.                ClrEol;
  1620.  
  1621.                IF ( Choice <> 'C' ) THEN
  1622.                   BEGIN
  1623.                      WRITE('Replace (Y/N/C/ESC)? ');
  1624.                      Read_Kbd( Choice);
  1625.                      Choice := UpCase( Choice );
  1626.                   END;
  1627.  
  1628.                IF ( ORD( Choice ) = ESC ) THEN
  1629.                   BEGIN
  1630.                      Window( 1, 2, Max_Screen_Col, SUCC( Page_Size ) );
  1631.                      GoToXY(Column,ScreenLine);
  1632.                      WRITE(SearchString);
  1633.                      Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1634.                      DisplayKeys;
  1635.                      EXIT;
  1636.                   END;
  1637.  
  1638.                GoToXY( 1 , Max_Screen_Line );
  1639.                ClrEol;
  1640.  
  1641.                WRITE('Searching...');
  1642.  
  1643.                Window( 1, 2, Max_Screen_Col, SUCC( Page_Size ) );
  1644.                GoToXY( 1 , Line );
  1645.  
  1646.                IF Choice in ['C','Y'] THEN
  1647.                   BEGIN
  1648.  
  1649.                      L    := LENGTH( LineBuffer^[Line]^ );
  1650.                      IPos := Position + S_Len;
  1651.  
  1652.                      LineBuffer^[Line]^ :=
  1653.                         Substr( LineBuffer^[Line]^, 1, PRED( Position ) ) +
  1654.                         Replacement +
  1655.                         Substr( LineBuffer^[Line]^, IPos, L - IPos + 1 );
  1656.  
  1657.                      L    := LENGTH( LineBuffer^[Line]^ );
  1658.                      IPos := Position + Len;
  1659.  
  1660.                      Save_Pos := POS( SearchString,
  1661.                                       Substr( LineBuffer^[Line]^,
  1662.                                               IPos ,
  1663.                                               L - IPos + 1 ) );
  1664.  
  1665.                      IF ( Save_Pos > 0 ) THEN
  1666.                         Position := Save_Pos + IPos - 1
  1667.                      ELSE
  1668.                         Position := 0;
  1669.  
  1670.                   END
  1671.                ELSE
  1672.                   BEGIN
  1673.  
  1674.                      L    := LENGTH( LineBuffer^[Line]^ );
  1675.                      IPos := Position + S_Len;
  1676.  
  1677.                      Save_Pos := POS( SearchString,
  1678.                                       Substr( LineBuffer^[Line]^,
  1679.                                               IPos ,
  1680.                                               L - IPos + 1 ) );
  1681.  
  1682.                      IF ( Save_Pos > 0 ) THEN
  1683.                         Position := Save_Pos + IPos - 1
  1684.                      ELSE
  1685.                         Position := 0;
  1686.  
  1687.                   END;
  1688.  
  1689.                GoToXY( 1 , ScreenLine );
  1690.                ClrEol;
  1691.  
  1692.                WRITE( Substr( LineBuffer^[Line]^ , 1 , MaxECol ) );
  1693.  
  1694.             END;
  1695.  
  1696.       END;
  1697.  
  1698.    Window( 1, 1, Max_Screen_Col, Max_Screen_Line );
  1699.    GoToXY( 1 , Max_Screen_Line );
  1700.    ClrEol;
  1701.  
  1702.    Edit_Press_Any('End of replace.  Press any key to exit ...');
  1703.  
  1704.    DisplayKeys;
  1705.  
  1706. END   (* Replace *);
  1707.  
  1708. (*----------------------------------------------------------------------*)
  1709. (*                SaveUndo --- Save current text as undo text           *)
  1710. (*----------------------------------------------------------------------*)
  1711.  
  1712. PROCEDURE SaveUndo;
  1713.  
  1714. BEGIN (* SaveUndo *)
  1715. END   (* SaveUndo *);
  1716.  
  1717. (*----------------------------------------------------------------------*)
  1718. (*                Undo --- Undo current change                          *)
  1719. (*----------------------------------------------------------------------*)
  1720.  
  1721. PROCEDURE Undo;
  1722.  
  1723. BEGIN (* Undo *)
  1724. END   (* Undo *);
  1725.  
  1726. (*----------------------------------------------------------------------*)
  1727. (*           DeleteToEOL   --- Delete to end of line                    *)
  1728. (*----------------------------------------------------------------------*)
  1729.  
  1730. PROCEDURE DeleteToEOL;
  1731.  
  1732. BEGIN (* DeleteToEOL *)
  1733. END   (* DeleteToEOL *);
  1734.  
  1735. (*----------------------------------------------------------------------*)
  1736. (*                HandleFunc --- Execute editor function                *)
  1737. (*----------------------------------------------------------------------*)
  1738.  
  1739. PROCEDURE HandleFunc;
  1740.  
  1741. BEGIN (* HandleFunc *)
  1742.                                    (* Choose next thing to do based *)
  1743.                                    (* upon key entry                *)
  1744.    CASE KeyNum OF
  1745.  
  1746.       2:  SaveUndo;
  1747.  
  1748.       8:  BackSpace;
  1749.  
  1750.       9:  Tab;
  1751.  
  1752.      13:  Enter;
  1753.  
  1754.      20:  DeleteToEOL;
  1755.  
  1756.      21:  Undo;
  1757.  
  1758.      27:  Esc_Key;
  1759.  
  1760.     143:  BackTab;
  1761.  
  1762.     187:  Help;
  1763.  
  1764.     188:  Locate;
  1765.  
  1766.     189:  Search;
  1767.  
  1768.     190:  Replace;
  1769.  
  1770.     191:  Terminate;
  1771.  
  1772.     192:  InsertLine;
  1773.  
  1774.     193:  DeleteLine;
  1775.  
  1776.     196:  QuitNoSave;
  1777.  
  1778.     17,
  1779.     199:  Column := 1;
  1780.  
  1781.     5,
  1782.     200:  CursorUp;
  1783.  
  1784.     23,
  1785.     201:  FuncPgUp;
  1786.  
  1787.     19,
  1788.     203:  CursorLeft;
  1789.  
  1790.     4,
  1791.     205:  CursorRight;
  1792.  
  1793.     18,
  1794.     207:  FuncEnd;
  1795.  
  1796.     24,
  1797.     208:  CursorDown;
  1798.  
  1799.     22,
  1800.     210:  Ins;
  1801.  
  1802.     7,
  1803.     211:  Del;
  1804.  
  1805.     26,
  1806.     209:  FuncPgDn;
  1807.  
  1808.     1,
  1809.     243:  PrevWord;
  1810.  
  1811.     6,
  1812.     244:  NextWord;
  1813.  
  1814.     12,
  1815.     246:  EndFile;
  1816.  
  1817.     17,
  1818.     260:  BeginFile;
  1819.  
  1820.     ELSE  Menu_Beep;
  1821.  
  1822.    END (* Case *);
  1823.  
  1824. END   (* HandleFunc *);
  1825.  
  1826. (*----------------------------------------------------------------------*)
  1827. (*                Dispose_Lines --- Dispose memory for text lines       *)
  1828. (*----------------------------------------------------------------------*)
  1829.  
  1830. PROCEDURE Dispose_Lines;
  1831.  
  1832. VAR
  1833.    I: INTEGER;
  1834.  
  1835. BEGIN (* Dispose_Lines *)
  1836.  
  1837.    FOR I := 1 TO HighestLine DO
  1838.       IF ( LineBuffer^[I] <> EmptyLine ) THEN
  1839.          DISPOSE( LineBuffer^[I] );
  1840.  
  1841.    FREEMEM( LineBuffer , SIZEOF( LinePtr ) * IntMaxLines );
  1842.  
  1843.    DISPOSE( EmptyLine );
  1844.  
  1845. END   (* Dispose_Lines *);
  1846.  
  1847. (*----------------------------------------------------------------------*)
  1848. (*                Editor --- Begin editor main routine                  *)
  1849. (*----------------------------------------------------------------------*)
  1850.  
  1851. BEGIN (* Editor *)
  1852.                                    (* Initialize editor *)
  1853.  
  1854.    IF ( NOT Initialize( EditFileName ) ) THEN
  1855.       EXIT;
  1856.                                    (* Display screen    *)
  1857.    PrintRow;
  1858.                                    (* Main edit loop -- get key *)
  1859.                                    (* and process it            *)
  1860.    Edit_Done := FALSE;
  1861.  
  1862.    REPEAT
  1863.                                    (* Move to current position on screen *)
  1864.  
  1865.       GoToXY( Column , ScreenLine );
  1866.  
  1867.       SecNum := FALSE;
  1868.                                    (* Pick up character of input *)
  1869.  
  1870.       IF GetKey( SecNum , InKey ) THEN
  1871.          BEGIN
  1872.                                    (* If escape sequence, must be command. *)
  1873.                                    (* Otherwise, process as text.          *)
  1874.             IF SecNum THEN
  1875.                HandleFunc
  1876.             ELSE
  1877.                Character;
  1878.                                    (* Update screen display *)
  1879.             PrintRow;
  1880.  
  1881.          END
  1882.       ELSE
  1883.          GiveAwayTime( 4 );
  1884.  
  1885.    UNTIL Edit_Done;
  1886.                                    (* Deallocate memory used for text *)
  1887.    Dispose_Lines;
  1888.  
  1889. END   (* Editor *);
  1890.  
  1891. (*----------------------------------------------------------------------*)
  1892. (*           PibEditor --- Main program to get file name for editing    *)
  1893. (*----------------------------------------------------------------------*)
  1894.  
  1895. BEGIN (* PibEditor *)
  1896.                                    (* Don't update status Line *)
  1897.  
  1898.    Save_Do_Status_Time := Do_Status_Time;
  1899.    Do_Status_Time      := FALSE;
  1900.  
  1901.                                    (* Save screen *)
  1902.  
  1903.    Save_Partial_Screen( Saved_Screen, 5, 10, 75, 14 );
  1904.  
  1905.    Draw_Menu_Frame( 5, 10, 75, 14, Menu_Frame_Color, Menu_Title_Color,
  1906.                     Menu_Text_Color, 'Edit File' );
  1907.  
  1908.                                    (* Get name of file to edit *)
  1909.    EditFileName := '';
  1910.  
  1911.    TextColor( Menu_Text_Color_2 );
  1912.    WRITELN('Enter name of file to edit: ');
  1913.    WRITE('>');
  1914.  
  1915.    TextColor( Menu_Text_Color );
  1916.    Read_Edited_String( EditFileName );
  1917.    WRITELN;
  1918.                                    (* Restore screen *)
  1919.    Restore_Screen( Saved_Screen );
  1920.    Reset_Global_Colors;
  1921.  
  1922.                                    (* Save screen *)
  1923.  
  1924.    IF ( EditFileName <> CHR( ESC ) ) THEN
  1925.       BEGIN
  1926.  
  1927.          Save_Screen( Saved_Screen );
  1928.                                    (* Edit the file *)
  1929.          Editor( EditFileName );
  1930.                                    (* Restore screen *)
  1931.          Restore_Screen( Saved_Screen );
  1932.          Reset_Global_Colors;
  1933.  
  1934.       END;
  1935.                                    (* Restore status Line check *)
  1936.  
  1937.    Do_Status_Time := Save_Do_Status_Time;
  1938.  
  1939. END   (* PibEditor *);
  1940.